/* global ol MilStd */
/**
 * [positionProperty 样本点数组]
 * @param  {[Array]} 	positions [存放点的数组对象(格式：[{time: YYYY/MM/DD HH:mm:ss, lon: xxx, lat: xxx},{},...])]
 * @return {[property]} property  [样本点]
 */
let positionProperty = function (positions) {
	let property = new Cesium.SampledPositionProperty()
	let time = null
	let position = null
	for (let i = 0; i < positions.length; ++i) {
		position = Cesium.Cartesian3.fromDegrees(positions[i].lon, positions[i].lat)
		time = Cesium.JulianDate.fromDate(new Date(positions[i].time))
		property.addSample(time, position)
	}
	return property
}
/**
 * [carToDegrees 坐标转换，笛卡尔坐标转成经纬度]
 * @param  {[object]} cartesian                         [笛卡尔坐标]
 * @return {[object]} {lon：xxx, lat: xxx, height: xxx} [经纬度]
 */
let carToDegrees = function (cartesian) {
	let cartographic = Cesium.Cartographic.fromCartesian(cartesian)
	let longitude = Cesium.Math.toDegrees(cartographic.longitude)
	let latitude = Cesium.Math.toDegrees(cartographic.latitude)
	let height = cartographic.height
	return { lon: longitude, lat: latitude, height: height }
}

let carToDegreesArr = function (cartesian) {
	let cartographic = Cesium.Cartographic.fromCartesian(cartesian)
	let longitude = Cesium.Math.toDegrees(cartographic.longitude)
	let latitude = Cesium.Math.toDegrees(cartographic.latitude)
	let height = cartographic.height
	return [longitude, latitude, height]
}
/**
 * [calculateRadians 计算航向]
 * @positions 坐标数组[[lon,lat,height],[lon,lat,height]]
 * 选取前一个点和后一个点计算航向，如果需要弧度则返回Radian，需要角度则返回Angle
 */
let calculateAngle = function (positions) {
	// 弧度
	let Radian = 0
	// 角度
	let Angle = 0
	let x = positions[1][0] - positions[0][0]
	let y = positions[1][1] - positions[0][1]
	if (!(x === 0 && y === 0)) {
		if (y >= 0) {
			Radian = Math.asin(x / Math.sqrt(x * x + y * y))
			Angle = (-Radian * 180) / Math.PI
		} else if (x !== 0) {
			Radian = Math.asin(x / Math.sqrt(x * x + y * y))
			Angle = (Radian * 180) / Math.PI - 180
		} else {
			Radian = Math.acos(y / Math.sqrt(x * x + y * y))
			Angle = (Radian * 180) / Math.PI + (90 * Radian) / Math.abs(Radian)
		}
	}
	return Angle
}
/**
 * [positionTranslation 计算点位平移]
 * @param  {[Cartesian3]} position [需要平移的点]
 * @param  {[Nember]}     X        [x方向的平移量]
 * @param  {[Nember]}     Y        [Y方向的平移量]
 * @param  {[Nember]}     Z        [Z方向的平移量]
 * @return {[Cartesian3]} position [平移后的点]
 * 局部坐标系以平移点为原点，东为x轴，北为y轴，上为z轴建立
 */
let positionTranslation = function (position, X, Y, Z) {
	let x = X || 0
	let y = Y || 0
	let z = Z || 0
	return Cesium.Matrix4.getTranslation(
		Cesium.Matrix4.multiplyByTranslation(Cesium.Transforms.eastNorthUpToFixedFrame(position), new Cesium.Cartesian3(x, y, z), new Cesium.Matrix4()),
		new Cesium.Cartesian3()
	)
}
/**
 * [calculateSpherePosition 计算单位球形顶点]
 * @param  {[Number]} verticalStartAngle   [垂直方向起始角]
 * @param  {[Number]} verticalEndAngle     [垂直方向截止角]
 * @param  {[Number]} horizontalStartAngle [水平方向起始角]
 * @param  {[NumberNumber]} horizontalEndAngle   [水平方向截止角]
 * @return {[Array]}  positions            [顶点数组]
 */
let calculateSpherePosition = function (verticalStartAngle = 0, verticalEndAngle = 180, horizontalStartAngle = 0, horizontalEndAngle = 360) {
	let n = 32
	let radius = 1
	let verticalStepAngle = ((verticalEndAngle - verticalStartAngle) / n) * (Math.PI / 180)
	let horizontalStepAngle = ((horizontalEndAngle - horizontalStartAngle) / n / 2) * (Math.PI / 180)
	let x
	let y
	let z
	let r
	let position = null
	let positions = []
	z = radius * Math.cos(verticalStartAngle * (Math.PI / 180))
	positions[positions.length] = 0
	positions[positions.length] = 0
	positions[positions.length] = z
	let j = z === 1 ? 1 : 0
	for (j; j < n + 1; ++j) {
		z = radius * Math.cos(verticalStartAngle * (Math.PI / 180) + verticalStepAngle * j)
		r = radius * Math.sin(verticalStartAngle * (Math.PI / 180) + verticalStepAngle * j)
		for (let i = 0; i <= 2 * n; ++i) {
			x = r * Math.cos(horizontalStepAngle * i)
			y = r * Math.sin(horizontalStepAngle * i)
			positions[positions.length] = x
			positions[positions.length] = y
			positions[positions.length] = z
		}
	}
	z = radius * Math.cos(verticalEndAngle * (Math.PI / 180))
	positions[positions.length] = 0
	positions[positions.length] = 0
	positions[positions.length] = z
	return positions
}
/**
 * [sphereIndices 球形索引，PrimitiveType为4]
 * @param  {[Number]}  stripe      [条带宽度]
 * @param  {[Number]}  interval    [条带间隔宽度]
 * @param  {[Boolean]} closeTop    [顶部是否闭合]
 * @param  {[Boolean]} closeBottom [底部是否闭合]
 * @return {[Array]}   indices     [索引数组]
 */
let sphereIndices = function (stripe = 1, interval = 0, closeTop = false, closeBottom = false) {
	let indices = []
	let n = 32
	if (closeTop) {
		for (let i = 1; i <= 2 * n; ++i) {
			indices[indices.length] = 0
			indices[indices.length] = i
			indices[indices.length] = i + 1
		}
		// indices[indices.length] = 0;
		// indices[indices.length] = 2 * n;
		// indices[indices.length] = 1;
	}
	for (let j = 1; j < n + 1; j += interval) {
		for (let k = 0; k < stripe; ++k) {
			for (let i = 0; i < 2 * n; ++i) {
				indices[indices.length] = i + 1 + (j - 1) * (2 * n + 1)
				indices[indices.length] = i + 1 + j * (2 * n + 1)
				indices[indices.length] = i + 2 + j * (2 * n + 1)
				indices[indices.length] = i + 1 + (j - 1) * (2 * n + 1)
				indices[indices.length] = i + 2 + j * (2 * n + 1)
				indices[indices.length] = i + 2 + (j - 1) * (2 * n + 1)
			}
			// indices[indices.length] = j * 2 * n ;
			// indices[indices.length] = (j + 1) * 2 * n ;
			// indices[indices.length] = j * 2 * n + 1;
			// indices[indices.length] = j * 2 * n;
			// indices[indices.length] = j * 2 * n + 1;
			// indices[indices.length] = (j - 1) * 2 * n + 1;
			j += 1
		}
	}
	if (closeBottom) {
		for (let i = n * (2 * n + 1) + 1; i <= (n + 1) * (2 * n + 1); ++i) {
			indices[indices.length] = i
			indices[indices.length] = i + 1
			indices[indices.length] = (n + 1) * (2 * n + 1) + 1
		}
		// indices[indices.length] = n * n * 2;
		// indices[indices.length] = (n - 1) * n * 2 + 1;
		// indices[indices.length] = n * n * 2 + 1;
	}
	return indices
}

let sphereLineIndices = function (stripe = 1, interval = 0) {
	let indices = []
	let n = 32
	for (let j = 0; j < n - interval; j += interval) {
		for (let k = 0; k < stripe; ++k) {
			for (let i = 0; i < 2 * n; ++i) {
				indices[indices.length] = i + 1 + j * (2 * n + 1)
				indices[indices.length] = i + 2 + j * (2 * n + 1)
				indices[indices.length] = i + 1 + (j + interval + 1) * (2 * n + 1)
				indices[indices.length] = i + 1 + j * (2 * n + 1)
			}

			indices[indices.length] = 2 * n + 1 + (j + interval + 1) * (2 * n + 1)
			indices[indices.length] = 2 * n + 1 + j * (2 * n + 1)
			j += 1
		}
	}

	for (let i = 0; i < 2 * n; ++i) {
		indices[indices.length] = i + 1 + n * (2 * n + 1)
		indices[indices.length] = i + 2 + n * (2 * n + 1)
	}
	return indices
}
/**
 * [createGeometryInstance 创建纯色实体]
 * @param  {[Array]}            positions   [顶点数组]
 * @param  {[Array]}            indices     [顶点索引]
 * @param  {[PrimitiveType]}    type        [连线类型]
 * @param  {[ModelMatrix]}      modelMatrix [模型矩阵]
 * @param  {[Color]}            color       [实体颜色]
 * @return {[GeometryInstance]} Geometry    [几何实体]
 */
let createGeometryInstance = function (positions, indices, type, modelMatrix, color) {
	return new Cesium.GeometryInstance({
		geometry: new Cesium.Geometry({
			attributes: new Cesium.GeometryAttributes({
				position: new Cesium.GeometryAttribute({
					componentDatatype: Cesium.ComponentDatatype.DOUBLE,
					componentsPerAttribute: 3,
					values: positions
				})
			}),
			indices: indices,
			primitiveType: type,
			boundingSphere: Cesium.BoundingSphere.fromVertices(positions)
		}),
		modelMatrix: modelMatrix,
		attributes: {
			color: Cesium.ColorGeometryInstanceAttribute.fromColor(color)
		}
	})
}
/**
 * [createGeometryInstanceWithColor 创建自定义颜色实体]
 * @param  {[Array]}            positions   [顶点数组]
 * @param  {[Array]}            indices     [顶点索引]
 * @param  {[PrimitiveType]}    type        [连线类型]
 * @param  {[ModelMatrix]}      modelMatrix [模型矩阵]
 * @param  {[Array]}            colors      [顶点颜色值]
 * @return {[GeometryInstance]} Geometry    [几何实体]
 */
let createGeometryInstanceWithColor = function (positions, indices, type, modelMatrix, colors) {
	return new Cesium.GeometryInstance({
		geometry: new Cesium.Geometry({
			attributes: new Cesium.GeometryAttributes({
				position: new Cesium.GeometryAttribute({
					componentDatatype: Cesium.ComponentDatatype.DOUBLE,
					componentsPerAttribute: 3,
					values: positions
				}),
				color: new Cesium.GeometryAttribute({
					componentDatatype: Cesium.ComponentDatatype.UNSIGNED_BYTE,
					componentsPerAttribute: 4,
					values: colors,
					normalize: true
				})
			}),
			indices: indices,
			primitiveType: type,
			boundingSphere: Cesium.BoundingSphere.fromVertices(positions)
		}),
		modelMatrix: modelMatrix,
		attributes: {
			show: new Cesium.ShowGeometryInstanceAttribute(true)
		}
	})
}
/**
 * [createPrimitive 创建自定义图元]
 * @param  {[Array]}   	 geometryInstances [实体数组，可为单个实体]
 * @return {[primitive]} primitive         [图元]
 */
let createPrimitive = function (geometryInstances) {
	return new Cesium.Primitive({
		geometryInstances: geometryInstances,
		appearance: new Cesium.PerInstanceColorAppearance({
			flat: true,
			translucent: true
		})
	})
}
/**
 * [arcPosition 圆弧形顶点]
 * @param  {[Number]} startAngle [开始角度]
 * @param  {[Number]} endAngle   [截止角度]
 * @return {[Array]}  positions  [顶点数组]
 */
let arcPosition = function (startAngle, endAngle) {
	let positions = []
	let n = 64
	let x
	let y
	let z
	let start = startAngle || 0
	let end = endAngle || 360
	let stepAngle = ((end - start) / n) * (Math.PI / 180)
	for (let i = 0; i < n; ++i) {
		x = Math.cos(stepAngle * i)
		y = Math.sin(stepAngle * i)
		positions[positions.length] = x
		positions[positions.length] = y
		positions[positions.length] = 0
	}
	return positions
}
/**
 * [circleLineIndices 圆线索引，PrimitiveType为1]
 * @return {[Array]} indices [索引数组]
 */
let circleLineIndices = function () {
	let indices = []
	let n = 64
	for (let i = 0; i < n - 1; ++i) {
		indices[indices.length] = i
		indices[indices.length] = i + 1
	}
	indices[indices.length] = n - 1
	indices[indices.length] = 0
	return indices
}
/**
 * [circleIndices 圆面索引,PrimitiveType为4]
 * @return {[Array]} indices [索引数组]
 */
let circleIndices = function () {
	let indices = []
	let n = 64
	for (let i = 0; i < n - 1; ++i) {
		indices[indices.length] = 2 * n
		indices[indices.length] = i
		indices[indices.length] = i + 1
	}
	indices[indices.length] = 2 * n
	indices[indices.length] = n - 1
	indices[indices.length] = 0
	for (let i = n; i < 2 * n - 1; ++i) {
		indices[indices.length] = 2 * n
		indices[indices.length] = i
		indices[indices.length] = i + 1
	}
	indices[indices.length] = 2 * n
	indices[indices.length] = 2 * n - 1
	indices[indices.length] = n
	for (let i = 0; i < n - 1; ++i) {
		indices[indices.length] = i
		indices[indices.length] = i + 1
		indices[indices.length] = i + 1 + n
		indices[indices.length] = i
		indices[indices.length] = i + 1 + n
		indices[indices.length] = i + n
	}
	indices[indices.length] = n - 1
	indices[indices.length] = 0
	indices[indices.length] = n
	indices[indices.length] = n - 1
	indices[indices.length] = n
	indices[indices.length] = 2 * n - 1
	return indices
}
/**
 * [sectorPosition 扇形顶点]
 * @param  {[Number]} startAngle [开始角度]
 * @param  {[Number]} endAngle   [截止角度]
 * @return {[Array]}  positions  [顶点数组]
 */
let sectorPosition = function (startAngle, endAngle) {
	let positions = arcPosition(startAngle, endAngle)
	positions[positions.length] = Math.cos((endAngle * Math.PI) / 180)
	positions[positions.length] = Math.sin((endAngle * Math.PI) / 180)
	positions[positions.length] = 0
	for (let i = 0; i < 65; ++i) {
		positions[positions.length] = positions[i * 3]
		positions[positions.length] = positions[i * 3 + 1]
		positions[positions.length] = 0.1
	}
	positions[positions.length] = 0
	positions[positions.length] = 0
	positions[positions.length] = 0
	return positions
}
/**
 * [sectorVertexIndices 扇形顶点索引,PrimitiveType为4]
 * @return {[Array]} indices [索引数组]
 */
let sectorVertexIndices = function () {
	let n = 64
	let indices = []
	for (let i = 0; i < n; i++) {
		indices[indices.length] = 2 * (n + 1)
		indices[indices.length] = i
		indices[indices.length] = i + 1
	}
	for (let i = 0; i < n; i++) {
		indices[indices.length] = 2 * (n + 1)
		indices[indices.length] = i + n + 1
		indices[indices.length] = i + 1 + n + 1
	}
	for (let i = 0; i < n; ++i) {
		indices[indices.length] = i
		indices[indices.length] = i + 1
		indices[indices.length] = i + 1 + n + 1
		indices[indices.length] = i
		indices[indices.length] = i + 1 + n + 1
		indices[indices.length] = i + n + 1
	}
	indices[indices.length] = 2 * (n + 1)
	indices[indices.length] = 0
	indices[indices.length] = n + 1
	indices[indices.length] = 2 * (n + 1)
	indices[indices.length] = 2 * (n + 1) - 1
	indices[indices.length] = n
	return indices
}
/**
 * [sectorVertexColor 扇形顶点颜色值]
 * @param  {[Array]} rgb    [预设颜色值]
 * @return {[Array]} colors [颜色值数组]
 */
let sectorVertexColor = function (rgb) {
	let n = 64
	let stepAlpha = 255 / n
	let colors = []
	for (let i = 0; i < (n + 1) * 4; i += 4) {
		colors[colors.length] = rgb[0]
		colors[colors.length] = rgb[1]
		colors[colors.length] = rgb[2]
		colors[colors.length] = 255 - (stepAlpha * i) / 4
	}
	for (let i = 0; i < (n + 1) * 4; i += 4) {
		colors[colors.length] = rgb[0]
		colors[colors.length] = rgb[1]
		colors[colors.length] = rgb[2]
		colors[colors.length] = 255 - (stepAlpha * i) / 4
	}
	colors[colors.length] = rgb[0]
	colors[colors.length] = rgb[1]
	colors[colors.length] = rgb[2]
	colors[colors.length] = 255
	return colors
}
/**
 * [coordinateTransform 坐标转换,将84坐标转换为墨卡托坐标]
 * @param  {[Array]} wgs84Coordinate [84坐标(格式：[lon,lat])]
 * @return {[Array]}                 [墨卡托坐标]
 */
let coordinateTransform = function (wgs84Coordinate) {
	return ol.proj.transform(wgs84Coordinate, 'EPSG:4326', 'EPSG:3857')
}

let getArrowPosition = function (type, coords) {
	let points = []
	for (let i = 0; i < coords.length; ++i) {
		points.push(coordinateTransform(coords[i]))
	}
	let milParam = null
	let positions = null
	switch (type) {
		case 'SimpleArrow':
			milParam = new MilStd.MilstdParams({
				headHeightFactor: 0.15,
				headWidthFactor: 0.4,
				neckHeightFactor: 0.75,
				neckWidthFactor: 0.1,
				tailWidthFactor: 0.1,
				hasSwallowTail: true,
				swallowTailFactor: 0.5
			})
			positions = MilStd.Arrow.getArrowFromVert(points, 'SimpleArrow', milParam)
			break
		case 'DoubleArrow':
			milParam = new MilStd.MilstdParams({
				headHeightFactor: 0.15,
				headWidthFactor: 0.8,
				neckHeightFactor: 0.7,
				neckWidthFactor: 0.4
			})
			positions = MilStd.Arrow.getArrowFromVert(points, 'DoubleArrow', milParam)
			break
		case 'StraightArrow':
			milParam = new MilStd.MilstdParams({
				headHeightFactor: 0.1,
				headWidthFactor: 1.3,
				neckHeightFactor: 1.0,
				neckWidthFactor: 0.7,
				tailWidthFactor: 0.07,
				hasSwallowTail: false,
				swallowTailFactor: 0
			})
			positions = MilStd.Arrow.getArrowFromVert(points, 'StraightArrow', milParam)
			break
		default:
			return
	}
	return positions
}
/**
 * [createSmoothCurvePoints 插值点]
 * @param  {[Array]}   points           [原始点，格式:[lon,lat,lon,lat,...]]
 * @param  {[Number]}  tension          [张力弧度,默认0.5]
 * @param  {[Boolean]} closed           [是否闭合,默认false]
 * @param  {[Number]}  numberOfSegments [片段数，默认16]
 * @return {[Array]}   result           [插值后的点数组]
 */
let createSmoothCurvePoints = function (points, tension, closed, numberOfSegments) {
	if (points.length < 4) {
		return points
	}
	tension = tension ? tension : 0.5
	closed = closed ? true : false
	numberOfSegments = numberOfSegments ? numberOfSegments : 16
	let ps = points.slice(0)
	let result = []
	let x
	let y
	let t1x
	let t2x
	let t1y
	let t2y
	let c1
	let c2
	let c3
	let c4
	let st
	let t
	let i
	if (closed) {
		ps.unshift(points[points.length - 1])
		ps.unshift(points[points.length - 2])
		ps.unshift(points[points.length - 1])
		ps.unshift(points[points.length - 1])
		ps.push(points[0])
		ps.push(points[1])
	} else {
		ps.unshift(points[1])
		ps.unshift(points[0])
		ps.push(points[points.length - 2])
		ps.push(points[points.length - 1])
	}
	for (i = 2; i < ps.length - 4; i += 2) {
		t1x = (ps[i + 2] - ps[i - 2]) * tension
		t2x = (ps[i + 4] - ps[i - 0]) * tension
		t1y = (ps[i + 3] - ps[i - 1]) * tension
		t2y = (ps[i + 5] - ps[i + 1]) * tension
		for (t = 0; t <= numberOfSegments; t++) {
			st = t / numberOfSegments
			c1 = 2 * Math.pow(st, 3) - 3 * Math.pow(st, 2) + 1
			c2 = -(2 * Math.pow(st, 3)) + 3 * Math.pow(st, 2)
			c3 = Math.pow(st, 3) - 2 * Math.pow(st, 2) + st
			c4 = Math.pow(st, 3) - Math.pow(st, 2)
			x = c1 * ps[i] + c2 * ps[i + 2] + c3 * t1x + c4 * t2x
			y = c1 * ps[i + 1] + c2 * ps[i + 3] + c3 * t1y + c4 * t2y
			result.push(x)
			result.push(y)
		}
	}
	return result
}

export default {
	getPositionProperty: function (positions) {
		return positionProperty(positions)
	},
	getDegrees: function (cartesian) {
		return carToDegrees(cartesian)
	},
	getDegreesArr: function (cartesian) {
		return carToDegreesArr(cartesian)
	},
	getAngle: function (positions) {
		return calculateAngle(positions)
	},
	getSpherePosition: function (verticalStartAngle, verticalEndAngle, horizontalStartAngle, horizontalEndAngle) {
		return calculateSpherePosition(verticalStartAngle, verticalEndAngle, horizontalStartAngle, horizontalEndAngle)
	},
	getSphereIndices: function (stripe, interval, closeTop, closeBottom) {
		return sphereIndices(stripe, interval, closeTop, closeBottom)
	},
	getSphereLineIndices: function (stripe, interval, closeTop, closeBottom) {
		return sphereLineIndices(stripe, interval, closeTop, closeBottom)
	},
	getPrimitive: function (geometryInstances, modelMatrix) {
		return createPrimitive(geometryInstances, modelMatrix)
	},
	getArcPosition: function () {
		return arcPosition()
	},
	getCircleLineIndice: function () {
		return circleLineIndices()
	},
	getCircleIndice: function () {
		return circleIndices()
	},
	getGeometryInstance: function (positions, indices, type, modelMatrix, color) {
		return createGeometryInstance(positions, indices, type, modelMatrix, color)
	},
	getSectorPosition: function (startAngle, endAngle) {
		return sectorPosition(startAngle, endAngle)
	},
	getGeometryInstanceWithColor: function (positions, indices, type, modelMatrix, colors) {
		return createGeometryInstanceWithColor(positions, indices, type, modelMatrix, colors)
	},
	getSectorVertexIndices: function () {
		return sectorVertexIndices()
	},
	getSectorVertexColor: function (rgb) {
		return sectorVertexColor(rgb)
	},
	getSmoothCurvePoints: function (points, tension, closed, numberOfSegments) {
		return createSmoothCurvePoints(points, tension, closed, numberOfSegments)
	},
	getCoordinateTransform: function (wgs84Coordinate) {
		return coordinateTransform(wgs84Coordinate)
	},
	getArrowPosition: function (type, coords) {
		return getArrowPosition(type, coords)
	}
}
